package com.rbac.web.exception;

import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContextException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

/**
 * @author gengaoliu
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionAdvice {
  @ExceptionHandler({ServletRequestBindingException.class})
  @ResponseStatus(HttpStatus.UNAUTHORIZED)
  public String globalUnauthorizedException(Exception e) {
    log.warn(e.getMessage(), e);
    return e.getMessage();
  }

  @ResponseStatus(HttpStatus.BAD_REQUEST)
  @ExceptionHandler(MethodArgumentNotValidException.class)
  public String exceptionHandler(MethodArgumentNotValidException exception) {
    BindingResult result = exception.getBindingResult();
    StringBuilder stringBuilder = new StringBuilder();
    if (result.hasErrors()) {
      List<ObjectError> errors = result.getAllErrors();
      errors.forEach(
          p -> {
            FieldError fieldError = (FieldError) p;
            log.warn(
                "Bad Request Parameters: dto entity [{}],field [{}],message [{}]",
                fieldError.getObjectName(),
                fieldError.getField(),
                fieldError.getDefaultMessage());
            stringBuilder
                .append(fieldError.getField())
                .append(" : ")
                .append(fieldError.getDefaultMessage())
                .append("\n");
          });
    }
    return stringBuilder.toString();
  }

  @ExceptionHandler(MethodArgumentTypeMismatchException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public void methodArgumentTypeMismatchException(Exception exception) {
    log.warn(exception.getMessage(), exception);
  }

  @ExceptionHandler({
    ApplicationContextException.class,
    IllegalArgumentException.class,
    InfrastructureException.class,
    Exception.class
  })
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public String rbacException(Exception e) {
    log.warn(e.getMessage(), e);
    return e.getMessage();
  }
}
